/*
 * Node.h
 *
 *  Created on: 2011/08/07
 *      Author: naoki
 */

#ifndef INCLUDED_NTENGINE_SCENE_NODE_H
#define INCLUDED_NTENGINE_SCENE_NODE_H

#include "NTEngine/Math/Matrix3x4.h"
#include "NTEngine/Math/Matrix4x4.h"
#include "NTEngine/Math/Function.h"
#include "Scene/src/NodeTemplate.h"
#include "Scene/src/AnimationNode.h"
#include "Scene/src/SkinNode.h"
#include "NTEngine/Base/DebugStream.h"

namespace NTEngine {
using namespace Math;

namespace Scene {

class Node{
public:
	Node( const NodeTemplate* tmpl ) :
	mTranslation( 0.f, 0.f, 0.f ),
	mRotation( 0.f, 0.f, 0.f ),
	mScale( 1.f, 1.f, 1.f ),
	mChildren( 0 ),
	mChildNumber( 0 ),
	mTemplate( tmpl ),
	mAnimation( 0 ),
	mSkin( 0 ) {
	}
	~Node(){
		mTemplate = 0; //単なる参照
		mAnimation = 0;
		mSkin = 0;
	}
	void setChildren( Node** children, int childNumber ){
		mChildren = children;
		mChildNumber = childNumber;
	}
	void draw( const Matrix3x4& parentMatrix, const Vector3& color, float transparency ) const {
		//ワールド行列を作る
		Matrix3x4 w;
		w.setMul( parentMatrix, mTemplate->mTransform ); //デフォルトをかけて、
		w.translate( mTranslation );
		w.rotateY( mRotation.y );
		w.rotateX( mRotation.x );
		w.rotateZ( mRotation.z );
		w.scale( mScale );

		if ( mTemplate->mBatch ) {
			//セット
			if ( mSkin ) {
				// スキンメッシュの場合は親の空間でワールド空間を定義してやる
				Graphics::Manager().setWorldMatrix( parentMatrix );
			} else {
				Graphics::Manager().setWorldMatrix( w );
			}
			//描画
			mTemplate->mBatch->draw( color, transparency );
		}
		for ( int i = 0; i < mChildNumber; ++i ) {
			mChildren[ i ]->draw( w, color, transparency );
		}
	}
	void setAnimation( const AnimationNode* a ){
		mAnimation = a;
	}
	void removeAnimation(){
		mAnimation = 0;
		mTranslation.set( 0.f, 0.f, 0.f );
		mRotation.set( 0.f, 0.f, 0.f );
		mScale.set( 1.f, 1.f, 1.f );
	}
	void updateAnimation( float t ){
		if ( mAnimation ){
			mAnimation->update(
				&mTranslation,
				&mRotation,
				&mScale,
				t );
		}
		if ( mSkin ) {
			Matrix3x4 m = mTemplate->mLocal;
			m.translate( mTranslation );
			m.rotateY( mRotation.y );
			m.rotateX( mRotation.x );
			m.rotateZ( mRotation.z );
			m.scale( mScale );
			mSkin->update( m, mTemplate->mId );
		}
	}
	void setSkin( const SkinNode* skin ) {
		mSkin = skin;
	}
	int id() const {
		return mTemplate->mId;
	}
	const char* name() const {
		return mTemplate->mName;
	}
	const SkinNode* skin() const {
		return mSkin;
	}
	const Matrix3x4& offset() const {
		return mTemplate->mOffset;
	}
private:
	// アニメーション用
	Vector3 mTranslation;
	Vector3 mRotation;
	Vector3 mScale;
	Matrix3x4 mBone; // ボーン
	Node** mChildren;
	int mChildNumber;
	const NodeTemplate* mTemplate; // ベース
	const AnimationNode* mAnimation; // アニメーション
	const SkinNode* mSkin; // スキン

//	Matrix3x4* mCombinations; // 合成行列の配列用ポインタ
};

} //namespace Scene
} //namespace NTEngine

#endif // INCLUDED_NTENGINE_SCENE_NODE_H
